package org.okkam.refine.commands;

import org.okkam.refine.controller.ApplicationController;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
import java.util.Set;

//import org.apache.commons.math.stat.descriptive.DescriptiveStatistics;
//import org.apache.commons.math.stat.descriptive.rank.Median;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONWriter;

import com.google.refine.commands.Command;
import com.google.refine.ProjectManager;
import com.google.refine.model.Project;
import com.google.refine.model.ColumnModel;
import com.google.refine.model.Column;
import com.google.refine.model.Row;
import com.google.refine.browsing.Engine;
import com.google.refine.browsing.FilteredRows;
import com.google.refine.browsing.RowVisitor;
import com.google.refine.util.ParsingUtilities;

/** ********
 *   *****
 *    ***
 *     *
 * This class is used to delete entities with their okkam ID from Google refine. 
 * it expects all cells in the column to be deleted are proper okkam IDs
 * @author seid M. Yimam (seidymam@okkam.it)
 * @author luigi Selmi (selmi@okkam.it)
 *
 */
public class DeleteByOkkamIdCommand extends Command {
   
    static ApplicationController controller = null;
    
    protected RowVisitor createRowVisitor(Project project, int cellIndex, List values) throws Exception {
        return new RowVisitor() {
            int cellIndex;
            List  values;
            
            public RowVisitor init(int cellIndex, List<Float> values) {
                this.cellIndex = cellIndex;
                this.values = values;
                return this;
            }
            
            @Override
            public void start(Project project) {
                // nothing to do
            }
            
            @Override
            public void end(Project project) {
                // nothing to do
            }
            
            public boolean visit(Project project, int rowIndex, Row row) {
                try {
                    String val = (String) row.getCellValue(this.cellIndex);
                    this.values.add(val);
                } catch (Exception e) {
                }

                return false;
            }
        }.init(cellIndex, values);
    }


    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request, response);
    };
    
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {            
        try {
            ProjectManager.singleton.setBusy(true);
           
            Project project = getProject(request);
            ColumnModel columnModel = project.columnModel;
            Column column = columnModel.getColumnByName(request.getParameter("column_name"));
            int cellIndex = column.getCellIndex();

            List values = new ArrayList();//list of okkam  IDs to be deleted

            Engine engine = new Engine(project);
            JSONObject engineConfig = null;

            try {
                engineConfig = ParsingUtilities.evaluateJsonStringToObject(request.getParameter("engine"));
            } catch (JSONException e) {
                // ignore
            }

            engine.initializeFromJSON(engineConfig);

            FilteredRows filteredRows = engine.getAllFilteredRows();
           
            //populate values with the okkam ID from the filtered rows
            filteredRows.accept(project, createRowVisitor(project, cellIndex, values));
                      
            Iterator< String > okkamIdDelet=values.iterator();
            
            Set < String> OkkamIds = new HashSet< String >();
            
            //get unique OkkamIds to delete
            while(okkamIdDelet.hasNext()){
                OkkamIds.add(okkamIdDelet.next());
            }
            
            okkamIdDelet = OkkamIds.iterator();
            
            int countDelete = 0;
            String message = "";
            boolean correctOkkamId = true;
           
            //stop execution if the column have NON okkamID values, including blank
            while(okkamIdDelet.hasNext()){
                String okkamId = okkamIdDelet.next();
                if (okkamId == null) {
                    correctOkkamId = false;
                    message = "Some cells do not contain okkamID or empty to be deleted";
                    break;
                }
                if (!okkamId.startsWith("http://www.okkam.org/ens") || okkamId.equals("")) {
                    correctOkkamId = false;
                    message = "Some cells do not contain okkamID or empty to be deleted";
                    break;
                }
            }
    
            Iterator< String > okkamIdDeletUniqe = OkkamIds.iterator();
            
            if(correctOkkamId) {
             
            controller=new ApplicationController();
            
            while(okkamIdDeletUniqe.hasNext()){
                try
                {
                        String okkamId=okkamIdDeletUniqe.next();
                        if(controller.deleteEntity(okkamId)){
                            countDelete++;
                        }
                       
                }
                catch (Exception e) {
                   System.out.println("Unable to delete this Okkam ID \n" + e);
                }
            }
            
        }
            JSONWriter writer = new JSONWriter(response.getWriter());

            writer.object();
            
            if(!message.equals("")){
                writer.key("key");
                writer.value(message);
            }
            else{
                writer.key("key");
                writer.value(countDelete + " Entities are deleted"); 
            }

            writer.endObject();
        } catch (Exception e) {
            respondException(response, e);
        } finally {
            ProjectManager.singleton.setBusy(false);
        }
    };

}
